package de.sendorian.util.io;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.apache.log4j.Logger;
import org.hamcrest.Matcher;

import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
import com.google.common.io.Files;

import de.sendorian.util.matcher.FileTypeMatchers;


public class FileWriter {

    private static final Logger LOG = Logger.getLogger(FileWriter.class.getName());

    private static final Matcher<String> IGNORED_FILES = FileTypeMatchers.ignoredFiles();
    
    
    public boolean deleteFile(String path, String fileName) {
        File file = new File(path, fileName);
        if (!file.exists())
            return false;
        file.delete();
        return true;
    }


    public boolean write(byte[] data, String path, String fileName) throws IOException {
        try {
            File file = new File(path, fileName);
            Files.createParentDirs(file);
            
            if (file.exists()) {
                LOG.info("The file \"" + path + java.io.File.separator + fileName + "\" already exists. Skipping.");
                return false;
            }

            // create intermediate file for saving
            File tmpFile = new File(path, fileName + ".part");
            if (tmpFile.exists()) {
                tmpFile.delete();
            }
            
            Files.write(data, tmpFile);
            Files.move(tmpFile, file);
            
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    

    public List<String> deflateArchiveFlat(String path, String fileName) throws ZipException, IOException {
        ZipFile zipFile = new ZipFile(new File(path, fileName));

        Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
        List<String> fileNames = new ArrayList<String>();
        while (zipEntries.hasMoreElements()) {
            ZipEntry zipEntry = zipEntries.nextElement();
            String zipEntryName = zipEntry.getName();

            // do not create subdirectories, only use the file name
            if (zipEntryName.contains(File.separator)) {
                zipEntryName = zipEntryName.substring(zipEntryName.indexOf(File.separatorChar));
            }

            if (!zipEntry.isDirectory() && !IGNORED_FILES.matches(zipEntryName)) {
                InputStream in = null;
                byte[] data;
                try {
                    in = zipFile.getInputStream(zipEntry);
                    data = ByteStreams.toByteArray(in);
                } finally {
                    Closeables.closeQuietly(in);
                }
                fileNames.add(zipEntryName);
                write(data, path, zipEntryName);
            }
        }
        return fileNames;
    }
}
